package lumis.service.wsrp.consumer.doui;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import lumis.doui.source.IDataProvider;
import lumis.doui.source.ISourceData;
import lumis.doui.source.TabularData;
import lumis.doui.source.TabularSource;
import lumis.doui.source.field.ITabularSourceField;
import lumis.portal.PortalException;
import lumis.portal.UnexpectedException;
import lumis.portal.authentication.SessionConfig;
import lumis.service.wsrp.consumer.IPortletServiceManager;
import lumis.service.wsrp.consumer.PortletServiceManagerFactory;
import lumis.service.wsrp.consumer.producermanager.ClonedPortlet;
import lumis.service.wsrp.consumer.producermanager.ProducerEntityImpl;
import lumis.service.wsrp.consumer.producermanager.ProducerEntityManagerFactory;
import lumis.util.ITransaction;

import com.sun.portal.wsrp.common.stubs.v2.PortletDescription;
import com.sun.portal.wsrp.consumer.common.WSRPConsumerException;
import com.sun.portal.wsrp.consumer.producermanager.ProducerEntityManager;

/**
 * Data provider for cloned portlets.
 *
 * @version $Revision: 13092 $ $Date: 2011-05-28 18:19:06 -0300 (Sat, 28 May 2011) $
 * @since 6.0.0
 */
public class ClonedPortletDataProvider implements IDataProvider<TabularSource<ITabularSourceField>>
{
	private static String FIELD_PORTLET_HANDLE = "portletHandle";
	private static String FIELD_PORTLET_NAME = "name";
	private static String FIELD_PORTLET_FRIENDLY_NAME = "friendlyName";
	private static String FIELD_PORTLET_USE = "use";
	private static String FIELD_PORTLET_IS_CLONE = "clone";
	
	public void loadData(SessionConfig sessionConfig,
						TabularSource<ITabularSourceField> source,
						ITransaction transaction)
					throws PortalException
	{
		TabularSource<ITabularSourceField> tabularSource = (TabularSource<ITabularSourceField>) source;
		String serviceInstanceId = source.getDouiContext().getRequest().getServiceInstanceConfig().getId();
		ProducerEntityImpl producerEntity = obtainProducerEntity(serviceInstanceId);
		
		if (producerEntity != null)
		{
			TabularData tabularData = source.getData();
			IPortletServiceManager portletServiceManager = PortletServiceManagerFactory.getPortletServiceManager(serviceInstanceId);
			if (source.getParameterValue("portletHandle") == null)
			{
				// if no portlet handle was set, return all available portlets
				List<PortletDescription> offeredPortletsList = obtainOfferedPortletsList(producerEntity);
				Set<ClonedPortlet> clonedPortletsSet = obtainClonedPortletsList(producerEntity);
				fillTabularData(tabularData, offeredPortletsList, clonedPortletsSet,
						portletServiceManager);
			}
			else
			{
				// if a portlet handle was set, return it
				PortletDescription portlet = producerEntity.getPortletDescription((String) source
						.getParameterValue("portletHandle"));
				if (portlet != null)
				{
					createAndFillOfferedPortletRow(tabularData, portlet);
				}
				else
				{
					// try to get as a cloned portlet
					ClonedPortlet clonedPortlet = null;
					if (producerEntity.getRegistration() != null)
					{
						for (ClonedPortlet cp : producerEntity.getRegistration()
								.getClonedPortlets())
						{
							if (cp.getPortletHandle().equals(
									source.getParameterValue("portletHandle")))
							{
								clonedPortlet = cp;
								break;
							}
						}
						if (clonedPortlet != null)
						{
							createAndFillClonedPortletRow(tabularData, clonedPortlet,
									portletServiceManager);
						}
					}
				}
			}
			tabularData.sort(tabularSource);
		}
	}
	
	/**
	 * Obtain the producer entity.
	 * @param source	
	 * @return
	 * @throws PortalException
	 */
	ProducerEntityImpl obtainProducerEntity(String serviceInstanceId) throws PortalException
	{	
	
		ProducerEntityManager producerEntityManager = ProducerEntityManagerFactory.getProducerEntityManager(serviceInstanceId);
		ProducerEntityImpl producerEntity = null;
		
		try
		{
			// get producer entity
			if (!(producerEntityManager.getProducerEntityIds().isEmpty()))
			{
				producerEntity = (ProducerEntityImpl) producerEntityManager.getProducerEntity(producerEntityManager.getProducerEntityIds().iterator().next());
			}
			
			return producerEntity;
		}
		catch (WSRPConsumerException e)
		{
			throw new UnexpectedException(e);
		}				
	}
	
	/**
	 * Obtain the offered portlets to the given producer entity.
	 * @param producerEntity	the instance of ProducerEntityImpl.
	 * @return					the list of PortletDescription. 
	 */
	List<PortletDescription> obtainOfferedPortletsList(ProducerEntityImpl producerEntity)
	{
		List<PortletDescription> offeredPortletsList = producerEntity.getServiceDescription().getOfferedPortlets();
				
		return offeredPortletsList;
	}
	
	/**
	 * Obtain the cloned portlets to the given producer entity.
	 * @param producerEntity	the instance of ProducerEntityImpl.
	 * @return					the list of ClonedPortlet.
	 * @throws UnexpectedException
	 */
	Set<ClonedPortlet> obtainClonedPortletsList(ProducerEntityImpl producerEntity) throws UnexpectedException
	{
		Set<ClonedPortlet> clonedPortletsSet = new HashSet<ClonedPortlet>();
		if (producerEntity.getRegistration() != null)
		{
			clonedPortletsSet = producerEntity.getRegistration().getClonedPortlets();	
		}		
		return clonedPortletsSet;
	}
	
	/**
	 * Fills the tabular data with the portlets information.
	 * @param tabularData
	 * @param offeredPortletsList
	 * @param clonedPortletsList
	 */
	void fillTabularData(TabularData tabularData,
								List<PortletDescription> offeredPortletsList,
								Set<ClonedPortlet> clonedPortletsSet,
								IPortletServiceManager portletServiceManager)
					throws PortalException
	{
		for (PortletDescription offeredPortlet: offeredPortletsList)
		{
			createAndFillOfferedPortletRow(tabularData, offeredPortlet);
		}
		
		for (ClonedPortlet clonedPortlet: clonedPortletsSet)
		{
			createAndFillClonedPortletRow(tabularData, clonedPortlet, portletServiceManager);
		}
	}
	
	/**
	 * Creates a new row in the tabular data and fills it with the Portlet
	 * information.
	 * @param tabularData
	 * @param portletDescription
	 * @param isClone
	 */
	void createAndFillOfferedPortletRow(TabularData tabularData,
										PortletDescription portletDescription)
	{
		ISourceData row = tabularData.addRow();		
		
		row.put(FIELD_PORTLET_HANDLE, portletDescription.getPortletHandle());
		row.put(FIELD_PORTLET_FRIENDLY_NAME, "N/A");
		row.put(FIELD_PORTLET_USE, 0);		
		row.put(FIELD_PORTLET_NAME, portletDescription.getDisplayName().getValue());
		row.put(FIELD_PORTLET_IS_CLONE, false);
	}
	
	void createAndFillClonedPortletRow(TabularData tabularData,
										ClonedPortlet clonedPortlet,
										IPortletServiceManager portletServiceManager)
								throws PortalException
	{
		ISourceData row = tabularData.addRow();
		
		String portletName = portletServiceManager.getPortletName(clonedPortlet.getPortletHandle());
		
		row.put(FIELD_PORTLET_HANDLE, clonedPortlet.getPortletHandle());
		row.put(FIELD_PORTLET_FRIENDLY_NAME, (clonedPortlet.getName() != null)?clonedPortlet.getName():"N/A");
		row.put(FIELD_PORTLET_USE, clonedPortlet.getInterfaceInstanceIds().size());
		row.put(FIELD_PORTLET_NAME, portletName);
		row.put(FIELD_PORTLET_IS_CLONE, true);
	}
}